/*
 * Copyright (C) 2012 Rothens
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rpg.gfx;

import rpg.gfx.gui.Bar;
import rpg.gfx.gui.GUI;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import rpg.Game;
import rpg.Location;
import rpg.Maps.Map;
import rpg.Maps.MapTile;
import rpg.Tiles.RoadTile;
import rpg.entities.Sprite;
import rpg.entities.factories.SpriteFactory;
import rpg.entities.factories.CreatureFactory;
import rpg.entities.properties.CreatureProperty;
import rpg.gfx.light.LightSource;
import rpg.gfx.light.Lighting;
import rpg.util.SortedList;

/**
 * rothens.tarhely.biz
 *
 * @author Rothens
 */
public class Screen extends Bitmap {

    public GUI gui;
    private static Screen instance;

    public class Renderable {

        public MapTile[] tiles;
        public int width;
        public int height;
        public Location topLeft;
        public Location bottomRight;

        public Renderable(Map map, int cX, int cY) {
            topLeft = new Location(cX - 320, cY - 240, false, map);
            bottomRight = new Location(cX + 319, cY + 239, false, map);
            width = bottomRight.getTileX() - topLeft.getTileX() + 1;
            height = bottomRight.getTileY() - topLeft.getTileY() + 1;
            getTiles(map);
        }

        private void getTiles(Map map) {
            tiles = new MapTile[width * height];
            int start = topLeft.getMapCoordinate();
            for (int i = 0; i < width * height; i++) {
                int val = start + i % width + map.getWidth() * (i / width);

                tiles[i] = map.tiles[val];
            }
        }
	
	public boolean isInside(Location l){
		return (l.getTileX()>=topLeft.getTileX() && l.getTileY()>=topLeft.getTileY()
			&& l.getTileX()<=bottomRight.getTileX() && l.getTileY()<=bottomRight.getTileY());
	}
    }
    private Bitmap viewport;
    int time = 0;
    public int x = 0;
    public int y = 0;
    
    public List<LightSource> getLightSources(Renderable r){
	    List<LightSource> ret = new LinkedList<LightSource>();
	    for(LightSource ls : Game.getInstance().getActual().lightSources){
		    Location l = ls.getLocation();
		    Location topLeft = r.topLeft;
		    Location bottomRight = r.bottomRight;
		    		if(l.getTileX()>=topLeft.getTileX()-Lighting.MAX_DISTANCE &&
					l.getTileY()>=topLeft.getTileY()-Lighting.MAX_DISTANCE &&
					l.getTileX()<=bottomRight.getTileX()+Lighting.MAX_DISTANCE &&
					l.getTileY()<=bottomRight.getTileY()+Lighting.MAX_DISTANCE){
					ret.add(ls);
				}
	    }
	    return ret;
    }

    public synchronized static Screen getInstance() {
        return instance;
    }

    public Screen(int width, int height) {
        super(width, height);
        instance = this;
        gui = new GUI(width, height);
        viewport = new Bitmap(width, height);
    }

    public void render(Game game) {
        time++;

        CreatureFactory player = (CreatureFactory) SpriteFactory.getInstance(0);
        if (player != null) {
            CreatureProperty playerProperty = (CreatureProperty) player.getProp();
            if (playerProperty.getLocation() != null) {
                Location loc = playerProperty.getLocation();
                //viewport.draw(game.actual.whole, -(loc.getX() - 320) - game.player.xOffs, -(loc.getY() - 240) - game.player.yOffs);
                x = (loc.getX()) + player.getxRenderOffset();
                y = (loc.getY()) + player.getyRenderOffset();
                Renderable r = new Renderable(Game.getInstance().getActual(), x, y);
		//System.out.println(((x - 320) % 64)+";"+((y - 240) % 64));
                for (int i = 0; i < r.width * r.height; i++) {
                    int dx = (i % r.width) * 64 - ((x - 320) % 64);
                    int dy = (i / r.width) * 64 - ((y - 240) % 64);
                    viewport.draw(r.tiles[i].getLandscape().bitmap, dx, dy);
                    if (r.tiles[i].getRoad() != null) {
                        RoadTile rt = r.tiles[i].getRoad();
                        viewport.draw(rt.bitmaps[rt.getState()], dx, dy);
                    }
                    if (r.tiles[i].getLayer1() != null) {
                        viewport.draw(r.tiles[i].getLayer1().bitmap, dx, dy);
                    }

                }
                SortedList<Sprite> sortedList = new SortedList<Sprite>(new Comparator<Sprite>() {

                    @Override
                    public int compare(final Sprite a, final Sprite b) {
                        if (a.getProp().getLocation().getY() > b.getProp().getLocation().getY()) {
                            return 1;
                        }
                        if (a.getProp().getLocation().getY() < b.getProp().getLocation().getY()) {
                            return -1;
                        }
                        return 0;
                    }
                });
                for (Sprite e : SpriteFactory.getEntites()) {
                    if (e.isInView(r)) {
                        sortedList.add(e);
                    }
                }
                for (Sprite e : sortedList) {
                    viewport.draw(e.getDrawGraphics(), e.getxRenderOffset() - 32, e.getyRenderOffset() - 32);
                    if (e instanceof CreatureFactory) {
                        if (e.equals(player)) {
                            continue;
                        }
                        Bar health = e.getHealthBar();
                        viewport.draw(health, e.getxRenderOffset() - 16, e.getyRenderOffset() - 32);
                    }
                }

                for (int i = 0; i < r.width * r.height; i++) {
                    int dx = (i % r.width) * 64 - ((x - 320) % 64);
                    int dy = (i / r.width) * 64 - ((y - 240) % 64);
                    if (r.tiles[i].getLayer2() != null) {
                        viewport.draw(r.tiles[i].getLayer2().bitmap, dx, dy);
                    }
                }
            }

            //viewport.draw(((PlayerEvents) (player.getEh())).getEnergyBar(), 10, 460);
            //viewport.draw(((PlayerEvents) (player.getEh())).getHealthBar(), 10, 450);
            gui.renderGUI();
            viewport.draw(gui, 0, 0);
            /*
             * Inventory inv = Player.getInstance().getInventory(); Item itm =
             * inv.getItem("key_red"); if(itm != null){ viewport.draw(itm.icon,
             * 610, 410); } itm = inv.getItem("key_blue"); if(itm != null){
             * viewport.draw(itm.icon, 580, 410); } itm =
             * inv.getItem("key_green"); if(itm != null){
             * viewport.draw(itm.icon, 550, 410); }
             */
            //viewport.draw(fs.getText("Rothens textTest", (byte) 0), 200, 200);
	    //viewport.draw(fs.getText("[Rothens] " + ColorCodes.BLUE + "inline " + ColorCodes.CYAN + "színezett "+ ColorCodes.YELLOW +"szöveg.", (byte) 3, 0xff00), 0,400);
            draw(viewport, 0, 0);
        }
    }
}
